package org.pathlet.core;

import static org.pathlet.core.PathletConstants.SYS_ATTR_CLASSES_BASEDIR;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import org.pathlet.core.config.ConfigManager;
import org.pathlet.core.config.impl.JsonConfigManager;
import org.pathlet.util.ClassPathResource;
import org.pathlet.util.IOUtils;

/**
 * 配置信息的读取类，根据文件路径读取对应的配置文件。并转换为 ConfigManager 的对象实例。
 * 读取的配置文件是JSON格式，可以由多个文件组成，每个文件必选时完整的JSON格式文件。
 *   1. 读取后文件中的格式为${key}的内容会替换为Properties中的值。
 *   2. 多个文件的内容会合并解析为一个完整的JSon对象树。
 *   3. JSon对象树会被转换为ConfigManager的实例。ConfigManager是对配置信息的抽象，可以通过ConfigManager获取到所有的配置信息。
 *
 * @author Charlie Zhang
 *
 */
public class ConfigManagerAccessor {

	private String configEncoding;

	private File[] configFiles;

	private File[] propertyFiles;

	public ConfigManagerAccessor(File[] configFiles, File[] propertyFiles, String configEncoding) {
		this.configFiles = configFiles;
		this.propertyFiles = propertyFiles;
		this.configEncoding = configEncoding;
	}

	public String getConfigEncoding() {
		return configEncoding;
	}

	public File[] getConfigFiles() {
		return configFiles;
	}

	public File[] getPropertyFiles() {
		return propertyFiles;
	}


	/**
	 * Load configurations and instance the ConfigManager by them.
	 * @return
	 * @throws IOException
	 */
	public ConfigManager loadConfigManager() throws IOException {
		String[] jsonContents = new String[configFiles.length];
		String[] jsonContentNames = new String[configFiles.length];
		for(int i=0 ; i<configFiles.length ; i++) {
			File configFile = configFiles[i];
			if(configFile != null) {
				jsonContents[i] = IOUtils.toString(new FileInputStream(configFile), configEncoding);
				jsonContentNames[i] = configFile.getAbsolutePath();
			}
		}

		Properties prop = loadPlaceholder();
	    return new JsonConfigManager(jsonContents, jsonContentNames, prop);
    }


	protected void loadSysProperty(Properties props) throws IOException {
		ClassPathResource cpr = new ClassPathResource("/", ConfigManagerAccessor.class);

		String classesBasedir = cpr.getFile().getAbsolutePath();
		if(classesBasedir.endsWith(File.separator) == false) {
			classesBasedir += File.separator;
		}
		classesBasedir = classesBasedir.replace("\\", "/");

		props.setProperty(SYS_ATTR_CLASSES_BASEDIR, classesBasedir);
	}

	/**
	 * Load placeholder properties file content into Properties, and return it.
	 *
	 * @return
	 * @throws IOException
	 */
	protected Properties loadPlaceholder() throws IOException {
    	Properties props = new Properties();

    	if(propertyFiles != null) {
	    	//Load properties files one by one
	    	for(File propertyFile : propertyFiles) {
	    		InputStream is = null;

	    		try{
			    	is = new FileInputStream(propertyFile);
			    	Properties p = new Properties();
			    	p.load(is);
			    	props.putAll(p);
		    	}
				finally {
					if(is != null) is.close();
				}
	    	}
    	}

    	loadSysProperty(props);

    	return props;
	}

}
